#pragma once

#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/wait.h>

#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include <signal.h>
#include "Log.hpp"
#include "ThreadPool.hpp"
#include "Task.hpp"
#include "Daemon.hpp"
using namespace std;


const string defaultip = "0.0.0.0";
const int backlog = 6; // 但是一般不要设置的太大
extern Log lg;

enum
{
    UsageError = 1,
    SocketError,
    BindError,
    ListenError,
};

class TcpServer;

class ThreadData
{
public:
    ThreadData(int fd, const string &ip, const uint16_t &p, TcpServer *t): sockfd(fd), clientip(ip), clientport(p), tsvr(t)
    {}
public:
    int sockfd;
    string clientip;
    uint16_t clientport;
    TcpServer *tsvr;
};

class TcpServer
{
public:
    TcpServer(const uint16_t &port, const string &ip = defaultip)
        :  _port(port), _ip(ip)
    {
    }

    void InitServer()
    {
        _listensock = socket(AF_INET, SOCK_STREAM, 0);

        struct sockaddr_in _obj;
        bzero(&_obj, sizeof(_obj));
        _obj.sin_family = AF_INET;
        _obj.sin_port = htons(_port);
        _obj.sin_addr.s_addr = INADDR_ANY;

        socklen_t len = sizeof(_obj);
        if (bind(_listensock, (struct sockaddr *)&_obj, len) < 0)
        {
            lg(Fatal, "Server bind is error %s", strerror(errno));
            exit(BindError);
        }

        lg(Info, "Server bind is succes , socketfd is %d ,port :%d", _listensock, _port);

        // 监听
        if (listen(_listensock, backlog) < 0)
        {
            lg(Fatal, "Server listen is error %s", strerror(errno));
            exit(ListenError);
        }
        lg(Info, "Server listen is succes ");

        // Tcp是面向连接的，服务器一般是比较“被动的”，服务器一直处于一种，一直在等待连接到来的状态
    }
    /*void _test(int _sockefd, uint16_t &port, string &clientip)
    {
        
    }*/
    void Start()
    {
        Daemon();
        ThreadPool<Task>::GetInstance()->Start();
        lg(Info, "tcpServer is running....");
        for (;;)
        {
            struct sockaddr_in client;
            socklen_t len = sizeof(client);

            int _sockefd = accept(_listensock, (struct sockaddr *)&client, &len);
            if (_sockefd < 0)
            {
                lg(Warning, "accept error, errno: %d, errstring: %s", errno, strerror(errno));
                continue;
            }
            char clientip[32];
            inet_ntop(AF_INET, &(client.sin_addr), clientip, sizeof(clientip));
            uint16_t clientport = ntohs(client.sin_port);

            lg(Info, "get a new link..., sockfd: %d, client ip: %s, client port: %d", _sockefd, clientip);
            // pid_t id=fork();
            // if(id==0)
            // {
            //     close(_listensock);
            //     if(fork()>0)exit(0);
            //     _test(_sockefd, client.sin_port, _ip);
            //     close(_sockefd);
            //     exit(0);
            // }
            // close(_sockefd);
            // pid_t w_id=waitpid(id,nullptr,0);
            // // 1. 获取新连接
            // // 2. 根据新连接来进行通信

            Task t(_sockefd, clientip, clientport);
            ThreadPool<Task>::GetInstance()->Push(t);
        }
    }
    ~TcpServer() {}

private:
    int _listensock;
    uint16_t _port;
    string _ip;
};